package thread;

public class LiLun {
    /*
        多线程
            概念
                线程是一个单一的顺序执行流程。
                    代码看起来像是“串联”在一起，逐句执行。
                多线程就是多个单一顺序执行流程“一起”执行。
                    多个串联的语句并联在一起。
            顺序执行与并发执行
                顺序执行-程序从上之下一句一句的执行。
                    单独任何一条线程都是一个线性执行流程，程序从上到下一句一句执行。
                    顺序执行的缺点是代码之间有牵绊，如果上一句阻塞，后续代码则无法执行。
                并发执行
                    微观上走走停停，宏观上多个线程一起执行的现象称为“并发执行”。
                    多个线程之间就是并发执行的。
                    OS将时间划分为多时间片段（时间片），尽可能均匀分配给每一个线程，获取时间片段的线程被CPU运行，而其他线程全部等待。
            使用场景
                互不干扰
                    多线程通常用于在一个程序中需要同时处理多个互不干扰的任务
                多线程更快
                    单线程可以完成，但是多线程可以更快。
            线程的创建
                第一种创建线程形式
                    继承Thread来定义一个线程
                        重写run方法，在其中定义该线程的任务代码。
                    启动线程
                        需要调用线程的start()方法。
                    优点：
                        构简单，利用匿名内部类创建。
                    缺点：
                        存在继承冲突问题，java是单继承的，这会导致如果继承Thread就无法继承其他类去服用方法，这在实际开发中是非常不方便的。
                        线程与线程任务存在了必然的耦合关系，导致线程的重用性变差。
                第二种创建线程形式
                    单独定义线程任务
                        实现Runnable接口或Callable接口（线程池中常用）。
                        重写run方法，在其中定义该线程的任务代码。
                    启动线程
                        实例化线程任务。
                        实例化线程，同时将任务通过线程的构造器传递给线程。
                        调用线程的start()方法。
                匿名内部类形式创建
     */
    /*
        线程API
            什么是主线程
                JAVA程序中的任何代码都是靠线程执行的，main方法也不例外。
                当程序启动后，JVM会创建一条线程用于执行main方法，这条线程被JVM取名为“main”，因此我们也成它为“主线程”。

                Thread提供的静态方法：
                    static Thread currentThread()
                    该方法返回执行它的线程。

            查看线程相关信息
                Thread提供了获取线程信息的相关方法：
                    long getId()：返回该线程的标识符。
                    String getName()：返回该线程的名称。
                    int getPriority()：返回该线程的优先级。
                    boolean isAlive()：测试线程是否处于活动状态。
                    boolean isDaemon()：测试线程是否为守护线程。
                    boolean isInterrupted()：测试线程是否被中断。
     */

    /*
        常见线程方法
            - currentThread（）：Thread类中的静态方法，可以获取当前线程对象。
            - getName(): 获取线程的名字
            - getId():获取当前线程的id
            - getPriority():获取线程的优先级
            - setPriority(...):设置线程优先级
            - isAlive(): 判定线程是否是活着
            - isDaemon(): 判断线程是否是守护线程
            - setDaemon(boolean flag): 设置线程为守护线程(flag=true)
            - sleep(long time); 让线程处于休眠状态
            - interrupt()：中断正在休眠的线程
            - isInterrupted()：判断线程是否被中断
     */

    /*
        线程优先级设置
            在Java中，线程的优先级是一个整数值，用于指示线程相对于其他线程的优先执行级别。优先级较高的线程在CPU调度时有更高的机会获得执行时间，但这
            并不意味着高优先级的线程一定会总是优先执行。线程调度是由操作系统控制的，Java虚拟机（JVM）只是向操作系统建议线程的优先级，最终的调度决策
            取决于操作系统的调度策略。
                线程优先级的基本概念
                    1. 默认优先级：每个新创建的线程会继承其父线程的优先级。如果没有特别指定，线程的优先级默认为NORM_PRIORITY，这是Thread类的
                       一个常量，值为5。
                    2. 优先级范围：线程优先级的范围是从1到10。其中，MIN_PRIORITY表示最低优先级，值为1；MAX_PRIORITY表示最高优先级，值为10。
                    3. 设置优先级：可以通过setPriority(int priority)方法来设置线程的优先级。同样，可以通过getPriority()方法来获取线程的
                       当前优先级。
     */

    /*
        多线程API
            什么是进程
                进程是操作系统中正在运行的程序的实力。
                    它包含了程序的代码、数据以及程序执行所需的资源，如内存、文件和设备。
                    每个进程都是独立运行时，它们之间相互隔离，并且通过进程间通信机制进行交互。
                    进程是操作系统进行资源分配和调度的基本单位，可以同时运行多个进程，实现多任务和并发执行。
            什么事线程
                线程是进程内的执行单元，是程序执行的最小单位。
                    一个进程可以包含多个线程，这些线程共享进程资源。
                    与进程相比，线程的创建、切换和销毁的开销要小得多，并且线程之间的通信更加高效，因为它们共享了相同的地址空间。
            进程与线程的区别
                资源占用：
                    1.进程是操作系统分配资源的基本单位，每个进程有独立的内存空间、文件句柄等系统资源。
                    2.线程是进程内的执行单元，多个线程共享同一进程的资源。
                开销：
                    1.创建、切换和销毁进程的开销比较大，因为需要分配和回收整个进程自身的资源。
                    2.创建、切换和销毁线程的开销相对较小，线程共享进程的资源，只需要分配和回收栈和寄存器等线程私有的资源。
                并发性：
                    1.多个进程可以同时执行，每个进程都拥有自己的地址空间，互不干扰。
                    2.多个线程共享同一进程的资源，可以并发执行，但可能需要进行同步和互斥操作来确保数据一致性。

            线程优先级
                线程的切换是由线程调度控制的，我们无法通过代码来干涉，但是我们可以通过提高线程的优先级来最大程度的改善线程获取时间片的几率。
                线程的优先级被划分为10级，值分别为1-10，其中1最低，10最高。线程提供了3个常量来表示最低、最高以及默认优先级：
                    Thread.MIN_PRIORITY,
                    Thread.MAX_PRIORITY,
                    Thread.NORM_PRIORITY,
                   void setPriority(int newPriority)：设置线程的优先级。
     */

    /*
        Sleep阻塞
            Thread的静态方法sleep用于使当前线程进入阻塞状态：
                static void sleep(long ms)
            该方法会使当前线程进入阻塞状态指定毫秒，当阻塞指定毫秒后，当前线程重新进入Runnable状态，等待分配时间片。
            该方法声明抛出一个InterruptedException。调用方法需要捕获这个异常。
                使用线程的interrupt()方法可以中断一条正在sleep阻塞的线程，此时sleep方法会立即抛出中断异常：InterruptException。
     */

    /*
        守护线程
            守护线程与普通线程在表现上没有什么区别，我们只需要通过Thread提供的方法来设定即可：
                void setDaemon(boolean)
                当参数为true时该线程为守护线程
            守护线程的特点是，当进程中只剩下守护线程时，所有守护线程强制终止。
            GC就是运行在一个守护线程上的。
     */

    /*
        多线程
            多线程并发安全
                什么是并发安全问题
                    当多个线程并发操作同一临界资源，由于线程切换的时机不确定，导致执行顺序出现混乱产生不良后果。
                    临界资源：操作该资源的完整过程同一时刻只能被单个线程进行。
                    常见的临界资源：
                        多线程共享实例变量。
                        多线程共享静态公共变量。
     */

    /*
        synchronized关键字
            若想解决线程安全问题，需要将异步的操作变为同步操作。
                异步操作：多线程并发的操作，相当于各干各的。
                同步操作：又先后顺序的操作，相当你干完我再干。
                synchronized关键字是java中的同步锁

            同步方法：
                java再语法层面上加了一个关键字synchronized。
                被该关键字修饰的方法称为同步方法，多个线程不能同时在方法内部执行。

            同步运行带来的性能问题
                同步方法可以解决并发安全问题，可随之带来并发性能的明显降低。

            同步块
                同步代码块包含两部分：
                    一个作为锁的对象（同步监视器对象）的引用。
                    一个作为由这个锁保护的代码块。
                        语法：
                            synchronized(同步监视器对象){
                                //需要多线程同步运行的代码片段
                            }

            同步监视器对象的选取
                要求：
                    所有需要同步执行同步块代码的线程看到的同步监视器对象必须是同一个。
                    同步监视器对象只能是引用类型。

            合适的锁对象
                合适的锁对象在满足锁的基本条件：
                    必须是引用类型
                    多个需要同步执行该代码块线程看到的必须是同一个对象。
                适当的同步有效性：
                    存在并发安全时可以限制多个线程同步执行。
                    不存在并发安全时允许多个线程异步执行。
     */

    /*
        线程安全及解决方案
            安全与不安全
                多个线程并发执行时，仍旧能够保证数据的正确性，这种现象称之为线程安全。
                多个线程并发执行时，不能能够保证数据的正确性，这种现象称之为线程不安全。

            导致线程不安全的因素通常有那些？
                多个线程并发执行。
                个线程有共享数据集。
                多个线程在共享数据集上有更新操作。
     */

    /*
        并发安全API
            集合API中，下列集合都不是并发安全的：
                ArrayList
                LinkedList
                HashSet
            java.util.Collections提供静态方法可以将一个集合装换位并发安全的集合：
                public static <T> List<T> synchronizedList(List<T> list)
                public static <T> Set<T> synchronizedList(Set<T> s)
     */

    /*
        互斥锁
            互斥性是指多个线程执行不同的代码片段，但是这些代码片段不能同一时刻被执行。
            互斥性仍可使用synchronized实现。
                使用synchronized锁定多个需要互斥的代码片段。
                这些synchronized指定的同步监视器必须是同一个对象。
     */

    /*
        线程死锁分析
            多个线程并发执行，并且互相等待已经被对方线程正在占用的锁，导致陷入彼此等待对方释放锁的状态，这个过程称之为死锁。
     */

    /*
        线程同步注意事项
            死锁：不当的锁顺序可能导致死锁，即两个或更多线程永久等待彼此持有的锁。
            性能：过度使用同步会导致性能下降(会让线程顺序执行)，因为线程可能经常处于阻塞状态。
            可读性与维护性：过多的同步代码可能使代码难以阅读和维护。
            锁粒度：选择合适的锁粒度很重要，过细或过粗的锁粒度都可能影响性能。
     */

    /*
        网络编程
            聊天室
                服务端发送消息
                    服务端通过socket获取输出流，流连接为PrintWriter。
                    客户端通过socket获取输入流，流连接为BufferedReader。

                    客户端发送一句消息，服务端会将消息回复给客户端。
                    客户端接收到消息后输出到控制台。

                服务端实现消息转发
                    内部类可以访问外部类的成员
                        Server中定义一个集合
                        所有内部类均可以访问该集合

                服务端处理断开连接
                    在ClientHandler异常处理机制中添加finally处理客户端断开后操作。

                解决并发安全问题
                    多个线程访问集合
                        互斥集合的三个操作：添加，删除，遍历
     */
}
















